import { SLKFile, SlkObj, slkType, tsSlkType } from "../types/type";
import * as fs from "fs"
import * as path from "path"
import { SlkKey, SLKOption, slkTitle } from "./Tslk";


export class Lni {
    // 当前注释内容
    tempComment = "";
    // 当前字段名称
    tempName = "";
    tempFields: Array<string | number> = [];
    inFiled = false;

    tempSlkObj: SlkObj;

    tempFilePath = "";
    tempSlk: SLKFile = []

    public constructor() {
        this.tempSlkObj = {
            id: "",
            fields: []
        }
        this.tempFields = [];
        //初始化
        this.tempSlkObj = {
            id: "",
            fields: []
        }
    }

    public parseDir(dirPath: string) {
        let files = fs.readdirSync(dirPath);
        files.forEach(f => {
            if (f.indexOf(".ini")) {
                this.tempFilePath = "out\\" + dirPath + "//" + f.replace('.ini', ".json")
                this.parseLni(dirPath + "//" + f)
                this.genType();

                this.writeFile(
                    this.tempFilePath,
                    JSON.stringify(this.tempSlk, null, " ")
                )
                this.init();
            }
        })
    }

    /**
     * 解析lni文件
     * @param filePath 
     */
    public parseLni(filePath: string) {
        let fileContent = fs.readFileSync(filePath, "utf-8");
        let lines = fileContent.split("\r\n");
        let lineNum = 0;
        while (lineNum < lines.length) {
            if (lines[lineNum]) {
                this.parseLine(lines[lineNum])
            }
            lineNum = lineNum + 1;
        }
    }

    /**
     * 生成lni文件
     */
    public genLni(type: slkTitle, data: SLKOption, outPath: string = "./table") {
        let result = "";
        let outFilePath = outPath + "//" + type + ".ini";

        let k: SlkKey
        for (k in data) {
            let v: string | number | string[] | number[] = data[k]
            if (k == 'id') {
                result += `[${v}]\n`
            } else if (typeof v == "number" || typeof v == "string") {
                result += `${k} = ${v}\n`
            } else if (Array.isArray(v)) {
                result += `${k} =  {`;
                let vArray = v as string[] | number[];
                if (typeof vArray[0] == "number") {
                    result += vArray.join(",");
                } else {
                    result += `\n`;
                    result += vArray.join(",\n");
                }
                result += "}"
            }
        }
        this.writeFile(outFilePath, result)
    }

    public writeFile(filePath: string, content: string) {
        let tempDir = path.dirname(filePath);
        if (!fs.existsSync(tempDir)) {
            fs.mkdirSync(tempDir, { recursive: true });
        }
        fs.writeFileSync(filePath, content, "utf-8")
    }

    private init() {
        this.tempSlkObj = {
            id: "",
            fields: []
        }
        this.tempFields = [];
        this.tempSlk = []
        this.tempComment = ""
    }
    private parseLine(content: string) {
        if (content[0] == "[") {
            //存储物编信息
            if (this.tempSlkObj.id) {
                // 增加引用
                let a = this.tempSlkObj
                this.tempSlk.push(a);
                this.tempSlkObj = {
                    id: "",
                    fields: []
                }
            }
            // [XXXX] 物编的id
            this.tempSlkObj.id = content.replace("[", "").replace("]", "").trim();
            this.tempSlkObj.fields = [];

        } else if (content[0] == '-' || content[1] == '-') {
            // -- xx 注释
            this.tempComment = content.replace(/-/g, "").trim();
        } else if (content.indexOf("=") > 0) {
            // xx = yy
            let temp = content.split("=");
            let name = temp[0].trim();
            let value = temp[1].trim();


            if (value[0] == '"') {
                // xx == "string"
                let tempV = value as string
                this.tempSlkObj.fields.push({
                    name,
                    type: "STRING",
                    value: tempV.replace(/"/g, ''),
                    comment: this.tempComment
                })
            } else if (value[0] == "{") {
                // console.log("name",content)
                if (content.indexOf("}") > 0) {
                    // xx = {...}
                    this.tempSlkObj.fields.push({
                        name,
                        type: "ARRAY",
                        value,
                        comment: this.tempComment
                    })
                } else {
                    // xx = {
                    this.tempName = name
                    this.inFiled = true;
                }
            } else if (typeof (parseFloat(value)) == 'number') {
                // xx = 3 || xx = 3.3
                if (Number.isInteger(value)) {
                    this.tempSlkObj.fields.push({
                        name,
                        type: "INT",
                        value: parseFloat(value),
                        comment: this.tempComment
                    })
                } else {
                    this.tempSlkObj.fields.push({
                        name,
                        type: "REAL",
                        value: parseFloat(value),
                        comment: this.tempComment
                    })
                }
            }

        } else if (this.inFiled) {
            if (content.trim() == '}') {
                //字段结束标记 }
                this.tempSlkObj.fields.push({
                    name: this.tempName,
                    type: "ARRAY",
                    value: this.tempFields,
                    comment: this.tempComment
                })
                this.inFiled = false;
                this.tempFields = [];
            } else {
                //字段内容
                this.tempFields.push(content)
            }
        }
    }

    private genType() {
        if (this.tempSlk.length > 0) {
            let tempTypes: tsSlkType[] = [];

            let typeName = path.basename(this.tempFilePath, ".json");
            let typeFile = "types//" + typeName + ".ts";
            let content = `export type SLK${typeName} = {\n`;

            this.tempSlk.forEach(slk => {
                slk.fields.forEach(slkField => {
                    let typeIndex = tempTypes.findIndex(v => v.name == slkField.name);

                    let types: slkType[] = [];
                    let tsComments: { id: string, comment: string }[] = [];
                    let tsValues = [];

                    if (typeIndex > -1) {
                        types = tempTypes[typeIndex]["type"]
                        tsComments = tempTypes[typeIndex]["comment"]
                    }
                    //比较类型
                    if (types.indexOf(slkField.type) == -1) {
                        types.push(slkField.type)
                    }

                    if (tsComments.findIndex(v => v.comment == slkField.comment) == -1) {
                        tsComments.push({ id: slk.id, comment: slkField.comment })
                    }

                    if (typeIndex == -1) {
                        // console.log("d", tsComments)
                        tempTypes.push({
                            name: slkField.name,
                            type: types,
                            comment: tsComments,
                        })
                    } else {
                        // console.log("d", tsComments)
                        tempTypes[typeIndex]["type"] = types
                        tempTypes[typeIndex]["comment"] = tsComments
                    }

                })
            })
            content += `    _parent : string\n`
            content += `    id : string\n`


            tempTypes.forEach(t => {
                if (t.comment.length > 0) {
                    t.comment.forEach(c => {
                        content += `    //[${c.id}] ${c.comment}\n`
                    })
                }
                let tsTypes: string[] = [];
                t.type.forEach(t => {
                    if (t == "REAL" || t == "INT") {
                        tsTypes.push("number")
                    } else if (t == "STRING") {
                        tsTypes.push("string")
                    } else if (t == "ARRAY") {
                        tsTypes.push("string[]")
                        tsTypes.push("number[]")
                    }
                })
                content += `    ${t.name}? : ${tsTypes.join(" | ")}\n`
            })
            content += `}`

            this.writeFile(typeFile, content)
        }

    }
}